home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / MacMud / Mud 4.0 / MacMud.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-24  |  18.8 KB  |  889 lines  |  [TEXT/MPS ]

  1.  
  2. #include <XtcLib.h>
  3. #include <XtcElements.h>
  4. #include <XtcMessages.h>
  5.  
  6. #include <SetJmp.h>
  7. #include <Time.h>
  8. #include <Math.h>
  9. #include <CursorCtl.h>
  10.  
  11. #include "config.h"
  12. #include "rc.h"
  13. #include "MacMud.h"
  14.  
  15. #undef fopen
  16. #undef open
  17.  
  18. // Local Defines
  19.  
  20. #define DIR_FLAG 0x10
  21.  
  22. #define WNETICKINTERVAL 8
  23. #define MAXSTACK        32000L
  24. #define    SPLASHTIME        3        // Number of seconds to display splash sceen
  25.  
  26. // Global Variables
  27.  
  28. int                gRuntimeMem;
  29. Boolean            gRunning = false;
  30. Boolean            gProgramDone = false;
  31. THPrint            gPrintHdl = NULL;
  32. short            gDefaultFont = 0;
  33. short            gDefaultSize = 12;
  34. short            gDefaultFace = 0;
  35. short            gDefaultJust = UI_JustDefault;
  36. FSSpec            gLastFSSpec;
  37. Str255            gLastFileName;
  38. Boolean            gCancelOp;
  39.  
  40. Boolean            gLexActive;
  41. Boolean            gSocketActive;
  42. Boolean            gInterpActive;
  43. Boolean            gBackgroundOnly;
  44.  
  45. NMRec            gNMRec;
  46. Str255            gNotifyStr;
  47. Boolean            gNotifyPending;
  48.  
  49. short            __spin_abort;
  50.  
  51. static jmp_buf    gEnv;
  52. static THz        runtimeZone = NULL;
  53. static Ptr        runtimeHeapPtr = NULL;
  54.  
  55. extern int num_player;
  56. extern int lpmain(void);
  57. extern void read_config(void);
  58. extern void init_global_configs(void);
  59. extern pascal Boolean XtcProg(UI_ViewPtr view, UI_Action *action);
  60. extern void new_player(int new_socket, void *addr, int len);
  61. extern int game_is_being_shut_down;
  62. extern Boolean ChangeMudlibDir(long *dirID, short *volRef);
  63.  
  64. #pragma segment Main
  65.  
  66. pascal void NMResponseProc(NMRecPtr theNMRec)
  67. {
  68.     long theA5;
  69.  
  70.     theA5 = SetA5(theNMRec->nmRefCon);
  71.     NMRemove(theNMRec);
  72.     gNotifyPending = false;
  73.     SetA5(theA5);
  74. }
  75.  
  76. #pragma segment Main
  77.  
  78. void AlertUser(short error, short message)
  79. {
  80.     // Display an alert to inform the user of an error. Message acts
  81.     // as an index into a STR# resource of error messages. If no
  82.     // message is given, i.e. = 0, then use a standard message. If
  83.     // error is not noErr then display it as well.
  84.  
  85.     short itemHit;
  86.     Str255 msg1, msg2;
  87.  
  88.     if (!message) message = eStandardErr;
  89.  
  90.     if (!gBackgroundOnly) {
  91.         GetIndString(msg1, sStdStrings, message);
  92.         InitCursor();
  93.         if (error != noErr) {
  94.             NumToString(error, msg2);
  95.             ParamText(msg1, msg2, "\p", "\p");
  96.         } else ParamText(msg1, "\p", "\p", "\p");
  97.         itemHit = Alert(rUserAlert, NULL);
  98.     } else if (!gNotifyPending) {
  99.         gNotifyPending = true;
  100.         GetIndString(gNotifyStr, sStdStrings, message);
  101.         gNMRec.qType = nmType;
  102.         gNMRec.nmMark = 0;
  103.         gNMRec.nmIcon = 0;
  104.         gNMRec.nmSound = (Handle)-1;
  105.         gNMRec.nmStr = gNotifyStr;
  106.         gNMRec.nmResp = (NMProcPtr)NMResponseProc;
  107.         gNMRec.nmRefCon = SetCurrentA5();
  108.         NMInstall(&gNMRec);
  109.     }
  110. }
  111.  
  112. #pragma segment Main
  113.  
  114. pascal void FatalError(short error, short message)
  115. {
  116.     EventRecord theEvent;
  117.  
  118.     AlertUser(error, message);
  119.     while (gNotifyPending) {
  120.         if (!UI_HasWaitNextEvent) {
  121.             SystemTask();
  122.             GetNextEvent(everyEvent, &theEvent);
  123.         } else {
  124.             WaitNextEvent(everyEvent, &theEvent, 0x7fffffff, NULL);
  125.         }
  126.     }
  127.     ExitToShell();
  128. }
  129.  
  130. #pragma segment Main
  131.  
  132. void AlertMsg(ConstStr255Param theMsg, ConstStr255Param theParam)
  133. {
  134.     Boolean gotEvent;
  135.     DialogPtr theAlert;
  136.     EventRecord theEvent;
  137.     DialogRecord alertStorage;
  138.  
  139.     InitCursor();
  140.     ParamText(theMsg, theParam, "\p", "\p");
  141.     theAlert = GetNewDialog(rMsgAlert, &alertStorage, (WindowPtr)(-1));
  142.     ShowWindow(theAlert);
  143.     DrawDialog(theAlert);
  144.  
  145.     gotEvent = false;
  146.     while (!gotEvent) {
  147.         if (!UI_HasWaitNextEvent) {
  148.             SystemTask();
  149.             gotEvent = GetNextEvent(mDownMask + keyDownMask, &theEvent);
  150.         } else {
  151.             gotEvent = WaitNextEvent(mDownMask + keyDownMask, &theEvent, 0, NULL);
  152.         }
  153.     }
  154.     CloseDialog(theAlert);
  155. }
  156.  
  157. #pragma segment Initialize
  158.  
  159. Boolean IsBackroundOnly(void)
  160. {
  161.     Handle res;
  162.     Boolean backonly;
  163.  
  164.     backonly = false;
  165.     if ((res = GetResource('SIZE',1)) != NULL) {
  166.         backonly = BitTst(*res,5);
  167.     } else     if ((res = GetResource('SIZE',0)) != NULL) {
  168.         backonly = BitTst(*res,5);
  169.     } else     if ((res = GetResource('SIZE',-1)) != NULL) {
  170.         backonly = BitTst(*res,5);
  171.     }
  172.     if (res) ReleaseResource(res);
  173.     return backonly;
  174. }
  175.  
  176. #pragma segment Initialize
  177.  
  178. void MacInitialize(void)
  179. {
  180.     Ptr                p;
  181.     EventRecord        theEvent;
  182.     long            total, contig;
  183.     const long        *stackBasePtr = (void *)0x908;
  184.  
  185.     // Later we might change our stack requirements, then we can
  186.     // use SetApplLimit to increase stack space at this point,
  187.     // before calling MaxApplZone.
  188.  
  189.     SetApplLimit((Ptr)(*stackBasePtr - MAXSTACK));
  190.     MaxApplZone();
  191.  
  192.     // Initialize the Mac system
  193.  
  194.     MoreMasters();
  195.     MoreMasters();
  196.     MoreMasters();
  197.  
  198.     read_config();
  199.     gNotifyPending = false;
  200.     gBackgroundOnly = IsBackroundOnly();
  201.  
  202.     InitGraf(&qd.thePort);
  203.     if (!gBackgroundOnly) {
  204.         InitFonts();
  205.         InitWindows();
  206.         InitMenus();
  207.         TEInit();
  208.         InitDialogs(NULL);
  209.         InitCursor();
  210.     }
  211.  
  212.     FlushEvents(everyEvent, 0);
  213.  
  214.     // This next bit of code is necessary to let MultiFinder pull
  215.     // us to the front. All it needs is a little time.
  216.  
  217.     (void) EventAvail(everyEvent, &theEvent);
  218.     (void) EventAvail(everyEvent, &theEvent);
  219.     (void) EventAvail(everyEvent, &theEvent);
  220.  
  221.     // Lets make sure that the machine has at least 128K ROMs. If it doesn't, die.    
  222.  
  223.     if (UI_Mac.machineType < 0)
  224.         FatalError(sStdStrings, eWrongMachine);    
  225.  
  226.     if ((ulong)GetApplLimit() - (ulong)ApplicZone() < kMinHeap)
  227.         FatalError(sStdStrings, eSmallSize);
  228.  
  229.     // Next, make sure that enough memory is free for our application to run. It
  230.     // is possible for a situation to arise where the heap may have been of required
  231.     // size, but a large scrap was loaded which left too little memory. To check for
  232.     // this, we call PurgeSpace and compare the result with a value that we have
  233.     // determined as the minimum amount of free memory our application needs at
  234.     // initialization. 
  235.      
  236.     PurgeSpace(&total, &contig);
  237.     if (total < kMinSpace)
  238.         FatalError(sStdStrings, eNoMemory);
  239.  
  240.     // The extra benefit to waiting until after the Toolbox Managers have been
  241.     // initialized before checking memory is that we can now give the user an
  242.     // alert to tell him what happened. Although it is possible that the memory
  243.     // situation could be worsened by displaying an alert, MultiFinder would
  244.     // gracefully exit the application with an informative alert if memory
  245.     // became critical. Here we are acting more in a preventative manner to
  246.     // avoid future disaster from low-memory problems.
  247.  
  248.     // Is the desk scrap already in memory?
  249.     if (LoadScrap () == noScrapErr) {
  250.         // Try and initialize it
  251.         ZeroScrap ();
  252.     }
  253.  
  254.     // Initialize our global variables
  255.  
  256.     gProgramDone = false;
  257.  
  258.     // Initialize the Xtc UI library
  259.  
  260.     UI_InitInterface();
  261.  
  262.     // Read and initialize the configuration
  263.  
  264.     init_global_configs();
  265.  
  266.     // Initialize the current printer.
  267.  
  268.     if (!gBackgroundOnly) {
  269.         PrOpen();
  270.         if (PrError() == noErr) {
  271.             if ((gPrintHdl = (THPrint)NewHandle(sizeof(TPrint))) != NULL) {
  272.                 PrintDefault(gPrintHdl);
  273.             } else AlertUser(sStdStrings, eNoPrinter);
  274.             PrClose();
  275.         } else AlertUser(sStdStrings, eNoPrinter);
  276.     }
  277.  
  278.     // Register all the view classes we are going to use.
  279.  
  280.     UI_RegisterClass('MAIN', XtcMain);
  281.  
  282.     if (!gBackgroundOnly) {
  283.         UI_RegisterClass('ABOT', XtcAboutBox);
  284.         UI_RegisterClass('SPLS', XtcSplashScreen);
  285.  
  286.         UI_RegisterClass('DEBG', XtcDebug);
  287.         UI_RegisterClass('CONS', XtcConsole);
  288.  
  289.         AddResMenu(GetMenu(M_APPLE), 'DRVR');
  290.         UI_LoadMenuBar(NULL, MAINMENUBAR, true);
  291.     }
  292. }
  293.  
  294. #pragma segment StandardFile
  295.  
  296. Boolean DoStandardGetFile(SFTypeList typeList, short numTypes)
  297. {
  298.     long response;
  299.  
  300.     if (UI_HasGestalt &&
  301.         Gestalt(gestaltStandardFileAttr, &response) == noErr && response != 0)
  302.     {
  303.         StandardFileReply theReply;
  304.  
  305.         StandardGetFile(NULL, numTypes, typeList, &theReply);
  306.         if (theReply.sfGood) {
  307.             memcpy(&gLastFSSpec,
  308.                     &theReply.sfFile, sizeof(gLastFSSpec));
  309.             return true;
  310.         }
  311.     } else {
  312.         Point where;
  313.         SFReply theReply;
  314.  
  315.         SetPt(&where, 80, 80);
  316.         typeList[0] = 'APPL';
  317.         SFGetFile(where, "\p", NULL, numTypes, typeList, NULL, &theReply);
  318.         if (theReply.good) {
  319.             FSSpec theSpec;
  320.  
  321.             theSpec.vRefNum = theReply.vRefNum;
  322.             theSpec.parID = *((ulong *)0x0398);
  323.             memcpy(&theSpec.name, theReply.fName, theReply.fName[0]+1);
  324.             return true;
  325.         }
  326.     }
  327.     return false;
  328. }
  329.  
  330. #pragma segment StandardFile
  331.  
  332. Boolean DoStandardPutFile(ConstStr255Param prompt, ConstStr255Param defaultName)
  333. {
  334.     long response;
  335.  
  336.     if (UI_HasGestalt &&
  337.         Gestalt(gestaltStandardFileAttr, &response) == noErr && response != 0)
  338.     {
  339.         StandardFileReply theReply;
  340.  
  341.         StandardPutFile(prompt, defaultName, &theReply);
  342.         if (theReply.sfGood) {
  343.             memcpy(&gLastFSSpec, &theReply.sfFile, sizeof(gLastFSSpec));
  344.             return true;
  345.         }
  346.     } else {
  347.         Point where;
  348.         SFReply theReply;
  349.  
  350.         SetPt(&where, 80, 80);
  351.         SFPutFile(where, prompt, defaultName, NULL, &theReply);
  352.         if (theReply.good) {
  353.             gLastFSSpec.vRefNum = theReply.vRefNum;
  354.             gLastFSSpec.parID = *((ulong *)0x0398);
  355.             memcpy(&gLastFSSpec.name, theReply.fName, theReply.fName[0]+1);
  356.             return true;
  357.         }
  358.     }
  359.     return false;
  360. }
  361.  
  362. #pragma segment StandardFile
  363.  
  364. static Boolean _sfnewopenflag;
  365.  
  366. pascal short SF6NewOpenDlgHook(short item, DialogPtr theDialog)
  367. {
  368. #pragma unused(theDialog)
  369.  
  370.     const short kNewButton = 11;
  371.     const short kCancelButton = 3;
  372.  
  373.     // If the user clicked on the "New" button we set our
  374.     // _sfnewopenflag flag variable to true and tell the
  375.     // StandardFile Dialog box that the user pressed quit,
  376.     // so we can call SFPutFile in our main program.
  377.  
  378.     if (item == kNewButton) {
  379.         _sfnewopenflag = true;
  380.         return kCancelButton;
  381.     } else return item;
  382. }
  383.  
  384. #pragma segment StandardFile
  385.  
  386. pascal short SF7NewOpenDlgHook(short item, DialogPtr theDialog, Ptr dataPtr)
  387. {
  388. #pragma unused(theDialog,dataPtr)
  389.  
  390.     const short kNewButton = 12;
  391.     const short kCancelButton = 2;
  392.  
  393.     // If the user clicked on the "New" button we set our
  394.     // _sfnewopenflag flag variable to true and tell the
  395.     // StandardFile Dialog box that the user pressed quit,
  396.     // so we can call StandardPutFile in our main program.
  397.  
  398.     if (item == kNewButton) {
  399.         _sfnewopenflag = true;
  400.         return kCancelButton;
  401.     } else return item;
  402. }
  403.  
  404. #pragma segment StandardFile
  405.  
  406. short DoStandardNewOpenFile(SFTypeList typeList, short numTypes, short *refNum)
  407. {
  408.     Point where;
  409.     long response;
  410.  
  411.     _sfnewopenflag = false;
  412.     if (UI_HasGestalt &&
  413.         Gestalt(gestaltStandardFileAttr, &response) == noErr && response != 0)
  414.     {
  415.         StandardFileReply theReply;
  416.  
  417.         SetPt(&where, 0, 0);
  418.         CustomGetFile(NULL, numTypes, typeList, &theReply, 6042,
  419.                         where, &SF7NewOpenDlgHook, NULL, NULL, NULL, NULL);
  420.         if (theReply.sfGood) {
  421.             short curFile;
  422.  
  423.             curFile = CurResFile();
  424.             SetResLoad(false);
  425.             *refNum = FSpOpenResFile(&theReply.sfFile, fsRdWrPerm);
  426.             SetResLoad(true);
  427.             if (ResError() != noErr)
  428.                 return -1;
  429.             UseResFile(curFile);
  430.             return true;
  431.         } else if (_sfnewopenflag) {
  432.             return 2;
  433.         }
  434.     } else {
  435.         SFReply theReply;
  436.  
  437.         SetPt(&where, 80, 80);
  438.         SFPGetFile(where, "\p", NULL, numTypes, typeList, NULL,
  439.                     &theReply, 4000, (ModalFilterProcPtr)&SF6NewOpenDlgHook);
  440.         if (theReply.good) {
  441.             short curFile;
  442.  
  443.             curFile = CurResFile();
  444.             SetResLoad(false);
  445.             *refNum = OpenRFPerm(theReply.fName, theReply.vRefNum, fsRdWrPerm);
  446.             SetResLoad(true);
  447.             if (ResError() != noErr)
  448.                 return -1;
  449.             UseResFile(curFile);
  450.             return true;
  451.         } else if (_sfnewopenflag) {
  452.             return 2;
  453.         }
  454.     }
  455.     return false;
  456. }
  457.  
  458. #pragma segment Project
  459.  
  460. void DoCloseAllWindows(void)
  461. {
  462.     UI_ViewPtr view;
  463.  
  464.     gCancelOp = false;
  465.     for (view = UI_WindowIsView(UI_FrontWindow());
  466.             view && !gCancelOp;
  467.             view = UI_WindowIsView((WindowPtr)((WindowPeek)view)->nextWindow))
  468.     {
  469.         UI_Action closeAction;
  470.         UI_ViewHeaderHdl viewHdl;
  471.  
  472.         viewHdl = ((UI_ViewPeek)view)->viewHdl;
  473.         if ((*viewHdl)->viewClass == 'TEXT')
  474.         {
  475. /*            UI_SendAction(UI_MakeAction(&closeAction),
  476.                             UIA_MenuSelect,
  477.                             (M_FILE * 0x10000) + M_FILE_CLOSE,
  478.                             view, NULL);
  479. */        }
  480.     }
  481. }
  482.  
  483. #pragma segment Main
  484.  
  485. pascal Boolean XtcMain(UI_ViewPtr view, UI_Action *action)
  486. {
  487.     switch (action->what)
  488.     {
  489.       case UIA_OpenApp:
  490.       {
  491.         return true;
  492.       }
  493.       case UIA_OpenDoc:
  494.       {
  495.         FInfo fndrInfo;
  496.         FSSpec *theFSS = (FSSpec *)action->code;
  497.  
  498.         FSpGetFInfo(theFSS, &fndrInfo);
  499.         return true;
  500.       }
  501.       case UIA_PrintDoc:
  502.       {
  503.         FInfo fndrInfo;
  504.         FSSpec *theFSS = (FSSpec *)action->code;
  505.  
  506.         FSpGetFInfo(theFSS, &fndrInfo);
  507.         return true;
  508.       }
  509.       case UIA_Quit:
  510.       {
  511.         gProgramDone = true;
  512.         startshutdowngame();
  513.         return true;
  514.       }
  515.       case UIA_InitMenus:
  516.       {
  517.         DisableItem(GetMHandle(M_APPLE), M_APPLE_PREFERENCES);
  518.         DisableItem(GetMHandle(M_EDIT), 0);
  519.         if (gRunning) {
  520.             DisableItem(GetMHandle(M_MISC), M_MISC_STARTUP);
  521.         } else {
  522.             DisableItem(GetMHandle(M_MISC), M_MISC_SHUTDOWN);
  523.             DisableItem(GetMHandle(M_FILE), M_FILE_NEW);
  524.         }
  525.         return true;
  526.       }
  527.       case UIA_MenuSelect:
  528.       {
  529.         switch (HiWord(action->code))
  530.         {
  531.           case M_APPLE:
  532.           {
  533.             switch (LoWord(action->code))
  534.             {
  535.               case M_APPLE_ABOUT:
  536.               {
  537.                   UI_ViewPtr about = UI_LoadView(kAboutView);
  538.  
  539.                 if (!about) {
  540.                     SysBeep(1);
  541.                     break;
  542.                 }
  543.                 UI_OpenView(about);
  544.                   break;
  545.               }
  546.               case M_APPLE_PREFERENCES:
  547.               {
  548.                 break;
  549.               }
  550.               default:
  551.               {
  552.                 Str255 name;
  553.                 GrafPtr savePort;
  554.  
  555.                 GetPort(&savePort);
  556.                 GetItem(GetMHandle(M_APPLE), LoWord(action->code), &name);
  557.                 OpenDeskAcc(name);
  558.                 SetPort(savePort);
  559.               }
  560.             }
  561.             break;
  562.           }
  563.           case M_FILE:
  564.           {
  565.             switch (LoWord(action->code))
  566.             {
  567.               case M_FILE_NEW:
  568.               {
  569.                 if (gProgramDone)
  570.                     break;
  571.                 if (num_player < MAX_PLAYERS) {
  572.                     new_player(0,NULL,0);
  573.                 } else {
  574.                     SysBeep(1);
  575.                 }
  576.                 break;
  577.               }
  578.               case M_FILE_QUIT:
  579.               {
  580.                 if (gRunning && !game_is_being_shut_down) {
  581.                     InitCursor();
  582.                     if (!num_player || Alert(rShutdownAlert, NULL) == ALERT_NO) {
  583.                         gProgramDone = true;
  584.                         startshutdowngame();
  585.                     }
  586.                     break;
  587.                 } else {
  588.                     gProgramDone = true;
  589.                 }
  590.                 break;
  591.               }
  592.             }
  593.               break;
  594.           }
  595.           case M_MISC:
  596.           {
  597.             switch (LoWord(action->code))
  598.             {
  599.               case M_MISC_STARTUP:
  600.               {
  601.                 if (!gRunning) {
  602.                     HiliteMenu( 0 );
  603.                     UI_UpdateMenuBar(view);
  604.                     RunMudlib();
  605.                     return true;
  606.                 } else {
  607.                     SysBeep(1);
  608.                 }
  609.                 break;
  610.               }
  611.               case M_MISC_SHUTDOWN:
  612.               {
  613.                 if (gRunning && !game_is_being_shut_down) {
  614.                     InitCursor();
  615.                     if (!num_player || Alert(rShutdownAlert, NULL) == ALERT_NO) {
  616.                         startshutdowngame();
  617.                     }
  618.                 } else {
  619.                     SysBeep(1);
  620.                 }
  621.                 break;
  622.               }
  623.               case M_MISC_SHOWMSG:
  624.               {
  625.                 break;
  626.               }
  627.             }
  628.             break;
  629.           }
  630.         }
  631.         HiliteMenu( 0 );
  632.  
  633.         UI_UpdateMenuBar(view);
  634.         return true;
  635.       }
  636.     }
  637.     return true;
  638. }
  639.  
  640. #pragma segment Splash
  641.  
  642. pascal Boolean XtcSplashScreen(UI_ViewPtr view, UI_Action *action)
  643. {
  644. #pragma unused(view,action)
  645.     return true;
  646. }
  647.  
  648. #pragma segment Splash
  649.  
  650. void DoSplashScreen()
  651. {
  652.     time_t start_time;
  653.     EventRecord theEvent;
  654.     UI_ViewPtr splashview;
  655.  
  656.     if ((splashview = UI_LoadView(kSplashView)) == NULL) {
  657.         ExitToShell();
  658.     }
  659.     UI_OpenView(splashview);
  660.  
  661.     time(&start_time);
  662.     while (difftime(time(NULL), start_time) < SPLASHTIME) {
  663.         if (!UI_HasWaitNextEvent) {
  664.             SystemTask();
  665.             GetNextEvent(0, &theEvent);
  666.         } else {
  667.             WaitNextEvent(0, &theEvent, UI_SleepTime(), NULL);
  668.         }
  669.     }
  670.     UI_DestructView(splashview);
  671. }
  672.  
  673. #pragma segment About
  674.  
  675. pascal Boolean XtcAboutBox(UI_ViewPtr view, UI_Action *action)
  676. {
  677.     if (action->what == UIA_MouseUp) {
  678.         UI_DestructView(view);
  679.         return true;
  680.     }
  681.     if (action->what == UIA_InitMenus) {
  682.         DisableItem(GetMHandle(M_APPLE), 0);
  683.         DisableItem(GetMHandle(M_FILE), 0);
  684.         DisableItem(GetMHandle(M_EDIT), 0);
  685.         DisableItem(GetMHandle(M_MISC), 0);
  686.         return true;
  687.     }
  688.     if (action->what == UIA_MenuSelect) {
  689.         return true;
  690.     }
  691.     return XtcMain(view, action);
  692. }
  693.  
  694. #pragma segment Main
  695.  
  696. void LPSetBusy(void)
  697. {
  698.     UI_BusyCursor = true;
  699. }
  700.  
  701. #pragma segment Main
  702.  
  703. void LPClearBusy(void)
  704. {
  705.     UI_BusyCursor = false;
  706.     SetCursor(&qd.arrow);
  707. }
  708.  
  709. #pragma segment Main
  710.  
  711. void XtcUnloadSeg(void)
  712. {
  713. }
  714.  
  715. #pragma segment Main
  716.  
  717. void LPEvents(void)
  718. {
  719.     Boolean            gotEvent;
  720.     UI_Action         theAction;
  721.     EventRecord        theEvent;
  722.  
  723.     if (!UI_HasWaitNextEvent) {
  724.         SystemTask();
  725.         gotEvent = GetNextEvent(everyEvent, &theEvent);
  726.     } else {
  727.         gotEvent = WaitNextEvent(everyEvent, &theEvent, 0, NULL);
  728.     }
  729.     UI_ProcessEvent(&theEvent, &theAction);
  730.     /*
  731.      * Only return true if we had a keydown or autokey and the
  732.      * event was not a menu selection event.
  733.      */
  734.     __spin_abort =
  735.         ((theEvent.what == keyDown || theEvent.what == autoKey) && !(theEvent.modifiers & cmdKey));
  736. }
  737.  
  738. #pragma segment Main
  739.  
  740. void LPRuntimeZone(void)
  741. {
  742.     if (runtimeHeapPtr)
  743.         SetZone(runtimeZone);
  744.     else DebugStr("\pLPRuntimeZone NULL?");
  745. }
  746.  
  747. #pragma segment Main
  748.  
  749. void LPApplicZone(void)
  750. {
  751.     SetZone(ApplicZone());
  752. }
  753.  
  754. #pragma segment Main
  755.  
  756. static Boolean InitRuntimeHeap(unsigned long heapSize)
  757. {
  758.     const short kZoneHeader = 52;                // 52 bytes for header 
  759.     const short kZoneTrailer = 12;                // 12 bytes for trailer 
  760.     const short kMPBlockHeader = 8;                // 8 bytes for Master Pointer block hdr 
  761.     const short kInitialMstrPtrs = 2;            // 2 master pointers created initially 
  762.     const short kSlop = 20;                        // bytes of slop (just in case) 
  763.     const short kZoneOverhead = kZoneHeader + kZoneTrailer + kMPBlockHeader + 4 * kInitialMstrPtrs + kSlop;// how large the zone overhead is 
  764.  
  765.     SetZone(ApplicZone());
  766.     if (heapSize) {
  767.         runtimeHeapPtr = NewPtr(((heapSize + 7)&~7) + kZoneOverhead);
  768.         if (runtimeHeapPtr == NULL)                    // can't allocate space for our heap 
  769.             return false;
  770.         InitZone(NULL, kInitialMstrPtrs,
  771.             runtimeHeapPtr + GetPtrSize(runtimeHeapPtr), runtimeHeapPtr);
  772.         runtimeZone = GetZone();
  773.         SetZone(ApplicZone());
  774.     } else if (runtimeHeapPtr) {
  775.         DisposPtr(runtimeHeapPtr);
  776.         runtimeHeapPtr = NULL;
  777.         runtimeZone = NULL;
  778.     }
  779.     return true;
  780. }
  781.  
  782. #pragma segmetn Main
  783.  
  784. Boolean ParseDirName(char *path, long *dirID, short *volRef)
  785. {
  786.     CInfoPBRec    pb;
  787.     Boolean        dirOK;
  788.  
  789.     c2pstr(path);
  790.     pb.hFileInfo.ioCompletion = NULL;
  791.     pb.hFileInfo.ioNamePtr = path;
  792.     pb.hFileInfo.ioVRefNum = 0;
  793.     pb.hFileInfo.ioDirID = 0;
  794.     pb.hFileInfo.ioResult = noErr;
  795.     pb.hFileInfo.ioFDirIndex = 0;
  796.     dirOK = (PBGetCatInfo(&pb, false) == noErr && (pb.hFileInfo.ioFlAttrib & DIR_FLAG));
  797.     p2cstr(path);
  798.     if (dirOK) {
  799.         *dirID = pb.hFileInfo.ioDirID;
  800.         *volRef = pb.hFileInfo.ioVRefNum;
  801.     }
  802.     return dirOK;
  803. }
  804.  
  805. #pragma segment Main
  806.  
  807. Boolean RunMudlib(void)
  808. {
  809.     extern long gMudLibDirID;
  810.     extern short gMudLibVolRef;
  811.  
  812.     if (!InitRuntimeHeap(gRuntimeMem)) {
  813.         // failed to allocate runtime heap
  814.         AlertUser(sStdStrings, eNoMemory);
  815.         return false;
  816.     }
  817.     gMudLibDirID = fsRtDirID;
  818.     gMudLibVolRef = 0;
  819.     if (ParseDirName(MUD_LIB, &gMudLibDirID, &gMudLibVolRef) == NULL) {
  820.         if (!gBackgroundOnly) {
  821.             if (!ChangeMudlibDir(&gMudLibDirID, &gMudLibVolRef))
  822.                 return false;
  823.         } else {
  824.             return false;
  825.         }
  826.     }
  827.     gRunning = true;
  828.     if (setjmp(gEnv) == 0) {
  829.         lpmain();
  830.     } else {
  831.         CloseConsole();
  832.     }
  833.     gRunning = false;
  834.     return true;
  835. }
  836.  
  837. #pragma segment Main
  838.  
  839. void LPExit(int code)
  840. {
  841.     if (code != 0) forceshutdowngame();
  842.     InitRuntimeHeap(0);
  843.     longjmp(gEnv, 0);
  844. }
  845.  
  846. #pragma segment Main
  847.  
  848. void main(void)
  849. {
  850.     extern sock_init();
  851.     extern sock_close_all();
  852.  
  853.     // Unload data segment: note that _DataInit must not be in Main!
  854.     UnloadSeg((ProcPtr) _DataInit);
  855.  
  856.     MacInitialize();
  857.  
  858.     if (!gBackgroundOnly) {
  859.         SetCursor(*GetCursor(watchCursor));
  860.         // Show our splash screen.
  861.         DoSplashScreen();
  862.     }
  863.  
  864.     UnloadSeg((ProcPtr) MacInitialize);
  865.  
  866.     if (!gBackgroundOnly) {
  867.         UnloadSeg((ProcPtr) XtcSplashScreen);
  868.         SetCursor(&qd.arrow);
  869.     }
  870.  
  871.     sock_init();
  872.  
  873.     if (gBackgroundOnly || AUTO_RESTART) {
  874.         while (RunMudlib()) ;
  875.         AlertUser(rUserAlert, eFailedToStart);
  876.     } else {
  877.         while (gRunning || !gProgramDone) {
  878.             LPEvents();
  879.             XtcUnloadSeg();
  880.         }
  881.     }
  882.     while (gNotifyPending) {
  883.         LPEvents();
  884.         XtcUnloadSeg();
  885.     }
  886.  
  887.     sock_close_all();
  888. }
  889.